package com.youlu.campus.service.notify;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import com.kuaidi100.sdk.api.QueryTrack;
import com.kuaidi100.sdk.api.QueryTrackMap;
import com.kuaidi100.sdk.api.SubscribeWithMap;
import com.kuaidi100.sdk.contant.ApiInfoConstant;
import com.kuaidi100.sdk.contant.CompanyConstant;
import com.kuaidi100.sdk.core.IBaseClient;
import com.kuaidi100.sdk.pojo.HttpResult;
import com.kuaidi100.sdk.request.QueryTrackParam;
import com.kuaidi100.sdk.request.QueryTrackReq;
import com.kuaidi100.sdk.request.SubscribeParam;
import com.kuaidi100.sdk.request.SubscribeParameters;
import com.kuaidi100.sdk.request.SubscribeReq;
import com.kuaidi100.sdk.response.QueryTrackMapResp;
import com.kuaidi100.sdk.response.QueryTrackResp;
import com.kuaidi100.sdk.response.SubscribePushData;
import com.kuaidi100.sdk.response.SubscribeResp;
import com.kuaidi100.sdk.response.SubscribeWithMapPushParamResp;
import com.kuaidi100.sdk.response.SubscribeWithMapPushResult;
import com.kuaidi100.sdk.utils.SignUtils;
import com.youlu.campus.base.exception.BusinessException;
import com.youlu.campus.common.base.QResult;
import com.youlu.campus.common.utils.DateTimeUtils;

import com.youlu.campus.entity.ExpressCompany;
import com.youlu.campus.entity.KuaiDi100;
import com.youlu.campus.entity.KuaiDi100RealTime;
import com.youlu.campus.entity.OOrderInfo;
import com.youlu.campus.entity.OrderInfo;
import com.youlu.campus.entity.enums.TaskBizType;
import com.youlu.campus.entity.kuaidi100.KuaiDi100PollMapBodyDTO;
import com.youlu.campus.entity.kuaidi100.KuaiDi100PushCompensate;
import com.youlu.campus.entity.platform.PlatformTaskInfo;
import com.youlu.campus.entity.platform.PlatformTaskTemMsg;
import com.youlu.campus.service.tms.ExpressCompanyService;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import ma.glasnost.orika.MapperFacade;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpStatus;
import org.apache.rocketmq.client.producer.SendCallback;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class KuaiDi100Service {

    @Value("${kuaidi.kuaidi100.key}")
    private String key;
    @Value("${kuaidi.kuaidi100.customer}")
    private String customer;
    @Value("${kuaidi.kuaidi100.secret}")
    private String secret;
    @Value("${kuaidi.kuaidi100.userid}")
    private String userId;

    @Value("${sys.pay.wx.bizDomain}")
    private String bizDomain;
    @Value("${mq.topic.clockRecord}")
    private String topic;

    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private ExpressCompanyService expressCompanyService;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Resource
    private RocketMQTemplate rocketMQTemplate;

    /**
     * 系统用户数据统计缓存前缀
     */
    private static final String KUAI_100_EXPRESS_RPEFIX = "youlu:system:kuaidi100:express:subOrderNo:%s:expressNo:%s";

    private static final String KUAI_100_NEW_EXPRESS_RPEFIX = "youlu:system:kuaidi100:new:express:expressNo:%s";

    private final static String FROM = "天津市天津市滨海新区大港学院路学院桥";

    private final static String FROM_BEIJING = "北京市昌平区马池口村新元科技园6号库";
    private static final String schema = "json";

    private final static String EMS_CODE = "";

    private final static String MAP_KEY = "DnsYV7RfN5vkNJP5Ex";

    @Autowired
    private MapperFacade mapperFacade;

    private final static String tips1 = "已定制完成，核验中";

    private final static String tips2 = "已核验完成，打包中";

    private final static String tips3 = "已打包完成，等待揽收";

    private final static String TIME = "2023-06-12 18:30:00";


    public SubscribePushData lastLogisticsResult(String number, String orderNo, Date shippingTime) {
        if (StringUtils.isAllBlank(number, orderNo) || Objects.isNull(shippingTime)) {
            log.error("【快递100】物流订单未发货 orderNo:{},number:{}", orderNo, number);
            return null;
        }
        Date date = DateTimeUtils.StringToDate(TIME, "yyyy-MM-dd HH:mm:ss");
        if (shippingTime.before(date)) {
            return null;
        }

        KuaiDi100 kuaiDi100 = queryTrackMap(number, orderNo, shippingTime);
        if (Objects.isNull(kuaiDi100) || Objects.isNull(kuaiDi100.getLastResult())) {
            return null;
        }
        List<SubscribePushData> dataList = kuaiDi100.getLastResult().getData();
        if (CollectionUtils.isEmpty(dataList)) {
            return null;
        }
        return dataList.get(0);
    }

    public void testInitPollMap(String number, String orderNo) {
        log.info("【test】number：{},orderNo:{} start", orderNo);
        String phone = "15207748006";
        String subOrderNo = "202305084317695118";
        String address = "广西壮族自治区南宁市武鸣区南宁师范大学武鸣校区桂圆12栋312宿舍";
        //  pushRollMap(  orderNo, subOrderNo,number, phone, address);
        log.info("【test】number：{},orderNo:{} end", orderNo);
    }

    public KuaiDi100 queryTrackMap(String number, String orderNo, Date shippingTime) {
        if (Objects.isNull(shippingTime)) {
            return null;
        }
        Date date = DateTimeUtils.StringToDate(TIME, "yyyy-MM-dd HH:mm:ss");
        if (shippingTime.before(date)) {
            return null;
        }
        Query query = new Query();
        query.addCriteria(Criteria.where("orderNo").is(orderNo));
        OrderInfo order = this.mongoTemplate.findOne(query, OrderInfo.class);
        if (Objects.isNull(order)) {
            return null;
        }
        String logisticsCompany = "";
        String mobile = order.getMobile();
        String address = order.getProvince() + order.getCity() + order.getArea() + order.getAddress();
        List<OOrderInfo> subOrderList = this.mongoTemplate.find(query, OOrderInfo.class);
        if (CollectionUtils.isNotEmpty(subOrderList)) {
            OOrderInfo oOrderInfo =
                    subOrderList.stream().filter(subOrder -> "4".equals(subOrder.getStatus()) && subOrder.getLogisticsNo().equals(number)).findFirst().orElse(null);
            if (Objects.nonNull(oOrderInfo)) {
                logisticsCompany = oOrderInfo.getLogisticsCompany();
            }
        }
        query = new Query();
        query.addCriteria(Criteria.where("number").is(number));
        KuaiDi100 kuaiDi100 = this.mongoTemplate.findOne(query, KuaiDi100.class);
        if (Objects.nonNull(kuaiDi100)) {
            kuaiDi100.setReceiveAddress(address);
            kuaiDi100.setReceiveMobile(mobile.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2"));
            kuaiDi100.setReceiveName(order.getName());
            kuaiDi100.setLogisticsCompany(logisticsCompany);
            return kuaiDi100;
        }
        kuaiDi100 = new KuaiDi100();
        kuaiDi100.setReceiveName(order.getName());
        kuaiDi100.setLogisticsCompany(logisticsCompany);
        kuaiDi100.setReceiveAddress(address);
        kuaiDi100.setReceiveMobile(mobile.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2"));
        kuaiDi100.setNumber(number);
        kuaiDi100.setStatus("polling");
        kuaiDi100.setBillstatus("got");
        SubscribeWithMapPushResult lastResult = new SubscribeWithMapPushResult();
        lastResult.setState("1");
        lastResult.setCom("ems");
        lastResult.setNu(number);
        lastResult.setStatus("200");
        lastResult.setCondition("00");
        OrderNoLogistics orderNoLogistics = new OrderNoLogistics(orderNo, number, shippingTime);
        String statusLogistics = orderNoLogistics.getStatus();
        List<SubscribePushData> dataList = new ArrayList<>();
        SubscribePushData subscribePushData = null;
        switch (statusLogistics) {
            case "核验中":
                subscribePushData = new SubscribePushData();
                subscribePushData.setStatus(orderNoLogistics.getStatus());
                subscribePushData.setContext(orderNoLogistics.getTips());
                subscribePushData.setTime(orderNoLogistics.getTime());
                subscribePushData.setStatusCode("-100");
                dataList.add(subscribePushData);
                break;
            case "打包中":
                subscribePushData = new SubscribePushData();
                subscribePushData.setStatus(orderNoLogistics.getStatus());
                subscribePushData.setContext(orderNoLogistics.getTips());
                subscribePushData.setTime(orderNoLogistics.getTime());
                subscribePushData.setStatusCode("-200");
                dataList.add(subscribePushData);
                subscribePushData = new SubscribePushData();
                subscribePushData.setStatus("核验中");
                subscribePushData.setContext(tips1);
                subscribePushData.setTime(orderNoLogistics.getCheckTime());
                subscribePushData.setStatusCode("-100");
                dataList.add(subscribePushData);
                break;
            case "等待揽收":
                subscribePushData = new SubscribePushData();
                subscribePushData.setStatus(orderNoLogistics.getStatus());
                subscribePushData.setContext(orderNoLogistics.getTips());
                subscribePushData.setTime(orderNoLogistics.getTime());
                subscribePushData.setStatusCode("-300");
                dataList.add(subscribePushData);
                subscribePushData = new SubscribePushData();
                subscribePushData.setStatus("打包中");
                subscribePushData.setContext(tips2);
                subscribePushData.setTime(orderNoLogistics.packTime);
                subscribePushData.setStatusCode("-200");
                dataList.add(subscribePushData);
                subscribePushData = new SubscribePushData();
                subscribePushData.setStatus("核验中");
                subscribePushData.setContext(tips1);
                subscribePushData.setTime(orderNoLogistics.getCheckTime());
                subscribePushData.setStatusCode("-100");
                dataList.add(subscribePushData);
                break;
        }

        lastResult.setData(dataList);
        kuaiDi100.setLastResult(lastResult);
        return kuaiDi100;
    }

    /**
     * 快递100没有物流信息时，自定义插入物流信息
     */
    @Getter
    @Setter
    class OrderNoLogistics {

        private String status;

        /**
         * 核验时间
         */
        private String checkTime;

        /**
         * 打包时间
         */
        private String packTime;

        private String tips;

        private String time;

        private String random() {
            int i = RandomUtils.nextInt(0, 59);
            if (i < 10) {
                return "0" + i;
            }
            return "" + i;
        }

        public OrderNoLogistics(String orderNo, String number, Date shippingTime) {
            log.info("【快递100】物流订单未发货 orderNo:{},number:{},shippingTime:{}", orderNo, number, LocalDateTime.ofInstant(shippingTime.toInstant(), ZoneId.systemDefault()).format(DateTimeFormatter.ofPattern("yyy-MM-dd HH:mm")));
            DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyy-MM-dd HH:mm:ss");
            LocalDateTime now = LocalDateTime.now();


            LocalDateTime localDateTimeShipping = LocalDateTime.ofInstant(shippingTime.toInstant(), ZoneId.systemDefault());
            //发货时间第三天
            LocalDateTime shippingTimeThird = localDateTimeShipping.plusHours(getRandomHour());
            String formatShippingTimeThird = shippingTimeThird.format(DateTimeFormatter.ofPattern("yyy-MM-dd HH")) + ":" + random() + ":" + random();
            LocalDateTime dateTime = LocalDateTime.parse(formatShippingTimeThird, dateTimeFormatter);
            if (now.isBefore(dateTime)) {
                formatShippingTimeThird = now.format(dateTimeFormatter);
            }
            //第五天
            LocalDateTime shippingTimeFifth = shippingTimeThird.plusHours(getRandomHour());
            String formatShippingTimeFifth = shippingTimeFifth.format(DateTimeFormatter.ofPattern("yyy-MM-dd HH")) + ":" + random() + ":" + random();
            dateTime = LocalDateTime.parse(formatShippingTimeFifth, dateTimeFormatter);
            if (now.isBefore(dateTime)) {
                formatShippingTimeFifth = now.format(dateTimeFormatter);
            }
            //如果当前时间小于三天时间
            if (now.isBefore(shippingTimeThird)) {
                this.status = "核验中";
                this.tips = tips1;
                this.time = localDateTimeShipping.format(dateTimeFormatter);
                log.info("核验中");
                return;
            }
            //如果当前时间小于三天时间小于第五天时间
            if (now.isBefore(shippingTimeFifth)) {
                this.status = "打包中";
                this.tips = tips2;
                this.time = formatShippingTimeThird;
                this.checkTime = localDateTimeShipping.format(dateTimeFormatter);
                return;
            }
            this.status = "等待揽收";
            this.tips = tips3;
            this.time = formatShippingTimeFifth;
            this.checkTime = localDateTimeShipping.format(dateTimeFormatter);
            this.packTime = formatShippingTimeThird;
        }

        private Integer getRandomHour() {
            List<Integer> list = Arrays.asList(40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55);
            int index = RandomUtils.nextInt(0, list.size());
            return list.get(index);
        }
    }


    public static void main(String[] args) {
        String json = "{\n" +
                "    \"result\": false,\n" +
                "    \"returnCode\": \"400\",\n" +
                "    \"message\": \"找不到对应公司\"\n" +
                "}";
        SubscribeResp subscribeResp = new Gson().fromJson(json, new TypeToken<SubscribeResp>() {
        }.getType());
        System.out.println(subscribeResp.getMessage() + "-" + subscribeResp.getReturnCode());
        System.out.println(RandomUtils.nextInt(0, 4));


    }

    private String wayBillCompany(String logisticsCompany) {
        if (StringUtils.isNotBlank(logisticsCompany) && logisticsCompany.contains("德邦")) {
            return CompanyConstant.DB;
        }
        if (StringUtils.isNotBlank(logisticsCompany) && logisticsCompany.contains("顺丰")) {
            return CompanyConstant.SF;
        }
        if (StringUtils.isNotBlank(logisticsCompany) && logisticsCompany.contains("圆通")) {
            return CompanyConstant.YT;
        }
        if (StringUtils.isNotBlank(logisticsCompany) && logisticsCompany.contains("韵达")) {
            return CompanyConstant.YD;
        }
        if (StringUtils.isNotBlank(logisticsCompany) && logisticsCompany.contains("申通")) {
            return CompanyConstant.ST;
        }

        if (StringUtils.isNotBlank(logisticsCompany) && logisticsCompany.contains("京东")) {
            return CompanyConstant.JD;
        }
        if (StringUtils.isNotBlank(logisticsCompany) && logisticsCompany.contains("中通")) {
            return CompanyConstant.ZT;
        }

        if (StringUtils.isNotBlank(logisticsCompany) && logisticsCompany.contains("汇通")) {
            return CompanyConstant.HT;
        }

        if (StringUtils.isNotBlank(logisticsCompany) && logisticsCompany.contains("宅急送")) {
            return CompanyConstant.ZJS;
        }
        return CompanyConstant.EMS;
    }


    /**
     * 根据单号重新订阅
     *
     * @param logisticsNoArr
     * @return
     */
    public QResult reSub(String[] logisticsNoArr) {
        ArrayList<String> failList = new ArrayList<>();
        for (String logisticsNo : logisticsNoArr) {
            Query querySubOrder = new Query().addCriteria(Criteria.where("logisticsNo").in(logisticsNo));
            List<OOrderInfo> subOrderInfos = mongoTemplate.find(querySubOrder, OOrderInfo.class);
            if (CollectionUtils.isEmpty(subOrderInfos)) {
                failList.add("未查询到子订单信息 logisticsNo:" + logisticsNo);
                continue;
            }
            for (OOrderInfo subOrderInfo : subOrderInfos) {
                Query query = new Query().addCriteria(Criteria.where("orderNo").is(subOrderInfo.getOrderNo()));
                OrderInfo orderInfo = mongoTemplate.findOne(query, OrderInfo.class);
                if (Objects.isNull(orderInfo)) {
                    log.error("未查询到订单信息 suborderNo:{},orderNo:{}", subOrderInfo.getOOrderNo(), subOrderInfo.getOrderNo());
                    failList.add("未查询到订单信息 orderNo:" + subOrderInfo.getOrderNo());
                    continue;
                }
                String from = orderInfo.getFrom();
                if (Objects.nonNull(from)) {
                    if (from.contains("[")) {
                        from = from.replaceAll("\\[", "");
                    }
                    if (from.contains("]")) {
                        from = from.replaceAll("]", "");
                    }
                }

                //订单订阅
                String address = orderInfo.getProvince() + orderInfo.getCity() + orderInfo.getArea() + orderInfo.getAddress();
                KuaiDi100PollMapBodyDTO dto =
                        KuaiDi100PollMapBodyDTO.builder().
                                number(logisticsNo).
                                to(address).
                                orderNo(orderInfo.getOrderNo())
                                .subOrderNo(subOrderInfo.getOOrderNo())
                                .phone(orderInfo.getMobile())
                                .from(from)
                                .logisticsCompany(orderInfo.getLogisticsCompany()).
                                build();
                this.pushRollMap(dto);
            }
        }
        return QResult.success(failList);
    }

    /**
     * 推送快递单号订阅地图轨迹
     *
     * @param dto 主订单号
     */

    @Async
    public void pushRollMap(KuaiDi100PollMapBodyDTO dto) {
        String phone = dto.getPhone();
        String from = dto.getFrom();
        String to = dto.getTo();
        String number = dto.getNumber();
        String subOrderNo = dto.getSubOrderNo();
        String orderNo = dto.getOrderNo();
        log.info("订阅运单号->{},手机号 ->{},orderNo:{},subOrderNo:{}", number, phone, orderNo, subOrderNo);
        if (StringUtils.isAllBlank(phone, from, to, number)) {
            log.error("订阅运单号->{},手机号 ->{} number:{}", number, phone, number);
            return;
        }
        SubscribeParam subscribeParam = new SubscribeParam();
        String logisticsCompany = dto.getLogisticsCompany();
        subscribeParam.setCompany(wayBillCompany(logisticsCompany));
        //运单号
        subscribeParam.setNumber(number);
        subscribeParam.setKey(this.key);
        subscribeParam.setFrom(from);
        subscribeParam.setTo(to);

        SubscribeParameters subscribeParameters = new SubscribeParameters();
        subscribeParameters.setPhone(phone);
        subscribeParameters.setCallbackurl(bizDomain + "/campus/public/kuaidi100/callback?number=" + number + "&orderNo" +
                "=" + orderNo + "&subOrderNo=" + subOrderNo);
        subscribeParameters.setResultv2("5");
        subscribeParam.setParameters(subscribeParameters);
        SubscribeReq subscribeReq = new SubscribeReq();
        subscribeReq.setSchema(ApiInfoConstant.SUBSCRIBE_SCHEMA);
        subscribeReq.setParam(new Gson().toJson(subscribeParam));
        IBaseClient subscribe = new SubscribeWithMap();
        try {
            log.info("运单号订阅请求参数->{}", JSONObject.toJSONString(subscribeReq));
            HttpResult executeResult = subscribe.execute(subscribeReq);
            log.info("运单号订阅返回结果->{}", executeResult.getBody());
            if (executeResult != null && executeResult.getStatus() == HttpStatus.SC_OK && StringUtils.isNotBlank(executeResult.getBody())) {
                SubscribeResp result = new Gson().fromJson(executeResult.getBody(), new TypeToken<SubscribeResp>() {
                }.getType());
                if (Objects.nonNull(result)) {
                    log.info("运单号订阅返回结果->result:{},message:{},returnCode:{}", result.isResult(), result.getMessage(), result.getMessage());
                    if (!result.isResult() && "601".equals(result.getReturnCode())) {
                        KuaiDi100PushCompensate kuaiDi100PushCompensate = mapperFacade.map(dto, KuaiDi100PushCompensate.class);
                        kuaiDi100PushCompensate.setSubscribeResp(result);
                        kuaiDi100PushCompensate.setStatus(1);
                        kuaiDi100PushCompensate.setCreatedTime(new Date());
                        Query query = new Query();
                        query.addCriteria(Criteria.where("number").is(number));
                        boolean exists = this.mongoTemplate.exists(query, KuaiDi100PushCompensate.class);
                        if (exists) {
                            return;
                        }
                        this.mongoTemplate.insert(kuaiDi100PushCompensate);
                    } else {
                        //推送补偿物流成功
                        if (StringUtils.isNotBlank(dto.getCompensatePushId())) {
                            KuaiDi100PushCompensate kuaiDi100PushCompensate = this.mongoTemplate.findById(dto.getCompensatePushId(), KuaiDi100PushCompensate.class);
                            if (Objects.nonNull(kuaiDi100PushCompensate)) {
                                Query query = new Query();
                                query.addCriteria(Criteria.where("number").is(number));
                                Update update = new Update();
                                update.set("status", 2);
                                update.set("updatedTime", new Date());
                                this.mongoTemplate.updateMulti(query, update, KuaiDi100PushCompensate.class);
                            }

                        }
                    }
                }
            } else {
                log.info("运单号订阅返回结果->http状态码:{},error:{}", executeResult.getStatus(), executeResult.getError());
                KuaiDi100PushCompensate kuaiDi100PushCompensate = mapperFacade.map(dto, KuaiDi100PushCompensate.class);
                kuaiDi100PushCompensate.setStatus(1);
                kuaiDi100PushCompensate.setCreatedTime(new Date());
                this.mongoTemplate.insert(kuaiDi100PushCompensate);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public SubscribeResp callBackUrl(HttpServletRequest request) {
        String param = request.getParameter("param");
        String number = request.getParameter("number");
        String orderNo = request.getParameter("orderNo");
        String subOrderNo = request.getParameter("subOrderNo");
        SubscribeResp subscribeResp = new SubscribeResp();
        log.info("快递100订阅推送回调结果|{}|{}", param, number);
        if (StringUtils.isAnyBlank(number, param)) {
            subscribeResp.setResult(Boolean.FALSE);
            subscribeResp.setReturnCode("500");
            subscribeResp.setMessage("失败，参数错误");
            return subscribeResp;
        }

        SubscribeWithMapPushParamResp subscribePushParamResp = new Gson().fromJson(param, SubscribeWithMapPushParamResp.class);
        if (Objects.nonNull(subscribePushParamResp)) {
            if (subscribePushParamResp.getLastResult() != null && "5".equals(subscribePushParamResp.getLastResult().getState())) {
                sendTemMsg(orderNo, subOrderNo);
            }
            String status = subscribePushParamResp.getStatus();
            if ("abort".equals(status) && StringUtils.isBlank(subscribePushParamResp.getComNew())) {
                Query query = new Query();
                query.addCriteria(Criteria.where("oOrderNo").is(subOrderNo));
                OOrderInfo subOrderInfo = this.mongoTemplate.findOne(query, OOrderInfo.class);
                if (Objects.nonNull(subOrderInfo)) {
                    query = new Query();
                    query.addCriteria(Criteria.where("orderNo").is(orderNo));
                    OrderInfo orderInfo = this.mongoTemplate.findOne(query, OrderInfo.class);
                    if (Objects.nonNull(orderInfo)) {
                        String from = orderInfo.getFrom();
                        if (Objects.nonNull(from)) {
                            if (from.contains("[")) {
                                from = from.replaceAll("[", "");
                            }
                            if (from.contains("]")) {
                                from = from.replaceAll("]", "");
                            }
                        }
                        //订单订阅
                        String address = orderInfo.getProvince() + orderInfo.getCity() + orderInfo.getArea() + orderInfo.getAddress();
                        KuaiDi100PollMapBodyDTO dto =
                                KuaiDi100PollMapBodyDTO.builder().
                                        number(subOrderInfo.getLogisticsNo()).
                                        to(address).
                                        orderNo(orderInfo.getOrderNo())
                                        .subOrderNo(subOrderInfo.getOOrderNo())
                                        .phone(orderInfo.getMobile())
                                        .from(from)
                                        .logisticsCompany(subOrderInfo.getLogisticsCompany()).
                                        build();
                        this.pushRollMap(dto);
                    }
                }
                subscribeResp.setResult(Boolean.TRUE);
                subscribeResp.setReturnCode("200");
                subscribeResp.setMessage("成功");
                return subscribeResp;
            }
            KuaiDi100 kuaiDi100 = mapperFacade.map(subscribePushParamResp, KuaiDi100.class);
            kuaiDi100.setNumber(number);
            kuaiDi100.setOrderNo(orderNo);
            Date now = new Date();
            Query query = new Query();
            query.addCriteria(Criteria.where("number").is(number));
            KuaiDi100 existKuaiDi100 = this.mongoTemplate.findOne(query, KuaiDi100.class);
            if (Objects.nonNull(existKuaiDi100)) {
                kuaiDi100.setId(existKuaiDi100.getId());
                kuaiDi100.setUpdatedTime(now);
                kuaiDi100.setCreatedTime(existKuaiDi100.getCreatedTime());
                kuaiDi100.getSubOrderNoSet().add(subOrderNo);
                this.mongoTemplate.save(kuaiDi100);
            } else {
                kuaiDi100.setCreatedTime(now);
                kuaiDi100.setUpdatedTime(now);
                kuaiDi100.getSubOrderNoSet().add(subOrderNo);
                this.mongoTemplate.save(kuaiDi100);
            }
        }
        subscribeResp.setResult(Boolean.TRUE);
        subscribeResp.setReturnCode("200");
        subscribeResp.setMessage("成功");
        return subscribeResp;
    }

    public void sendTemMsg(String orderNo, String subOrderNo) {
        Query query = new Query();
        query.addCriteria(Criteria.where("oOrderNo").is(subOrderNo));
        OOrderInfo orderInfo = this.mongoTemplate.findOne(query, OOrderInfo.class);
        if (orderInfo == null) {
            return;
        }
        if ("wechat-h5".equals(orderInfo.getPlatform())) {
            String appId = orderInfo.getAppId();
            String platform = orderInfo.getPlatform();
            Query platTaskQuery = new Query().addCriteria(Criteria.where("appId").is(appId)
                    .and("platform").is(platform).and("taskBizType").is(TaskBizType.PAY_SUBSCRIPTION)
                    .and("deleted").is(Boolean.FALSE));
            PlatformTaskInfo platformTaskInfo = mongoTemplate.findOne(platTaskQuery, PlatformTaskInfo.class);
            if (platformTaskInfo != null && CollectionUtils.isNotEmpty(platformTaskInfo.getTaskExtra())) {
                String tempId = platformTaskInfo.getTaskExtra().get(0);
                String openId = orderInfo.getOpenId();
                PlatformTaskTemMsg clockMsg = new PlatformTaskTemMsg();
                clockMsg.setOpenId(openId);
                clockMsg.setUserId(orderInfo.getAccountInfoId());
                clockMsg.setTemplateId(tempId);
                clockMsg.setAppId(appId);
                clockMsg.setPlatform(orderInfo.getPlatform());
                clockMsg.setActivityId(orderInfo.getActivityId());
                clockMsg.setToMini(true);
                clockMsg.setMiniAppId("wxc3211a2e49489560");
                String miniPagepath = "/pages/ca-order-detail?orderNo=" + orderNo;
                clockMsg.setMiniPagepath(miniPagepath);
                List<String> params = new ArrayList<>();
                params.add(orderInfo.getLogisticsCompany());
                params.add(fixLengthString(orderInfo.getLogisticsNo(), 10));
                String goodsName = truncateString(orderInfo.getItemTitle());
                String name = String.format("【%s】正在派送，查看详情", goodsName);
                params.add(name);
                clockMsg.setParams(params);
                clockMsg.setType("pay_order_subscribe");
                rocketMQTemplate.asyncSend(topic, clockMsg, new SendCallback() {
                    @Override
                    public void onSuccess(SendResult sendResult) {
                        log.info("【订阅发货信息】发送状态 ->{}", sendResult.getSendStatus());
                    }

                    @Override
                    public void onException(Throwable throwable) {
                        log.error("【支付订单订阅消息】消息失败", throwable);
                    }
                });
            }
        }
    }

    public static String truncateString(String str) {
        if (str == null || str.length() <= 9) {
            return str;
        }
        return str.substring(0, 8) + "…";
    }

    public static String fixLengthString(String str, int len) {
        if (str == null || str.length() <= len) {
            return str;
        }
        return str.substring(0, len);
    }

    public QueryTrackResp queryTrack(String orderNo) {
        log.info(":>>> 开始查询订单:{} 物流状态", orderNo);
        if (StringUtils.isBlank(orderNo)) {
            log.error(":>>> 订单号为空:{}", orderNo);
            throw new BusinessException("物流状态异常");
        }
        OOrderInfo oOrderInfo = this.getSubOrderInfo(orderNo);
        if (Objects.isNull(oOrderInfo)) {
            log.error(":>>> 子订单:{} 不存在", orderNo);
            throw new BusinessException("子订单不存在");
        }
        OrderInfo s = this.getOrderInfo(oOrderInfo.getOrderNo());
        if (StringUtils.isBlank(oOrderInfo.getLogisticsCompany()) || StringUtils.isBlank(oOrderInfo.getLogisticsNo())) {
            log.error(":>>> 物流公司:{} 或物流单号:{} 为空", oOrderInfo.getLogisticsCompany(), oOrderInfo.getLogisticsNo());
            throw new BusinessException("暂无物流信息");

        }
        QueryTrackResp resp = this.getTrackCache(oOrderInfo.getOOrderNo(), oOrderInfo.getLogisticsNo());
        if (Objects.nonNull(resp)) {
            log.info(":>>> 子订单:{},物流信息在缓存中:{}", orderNo, JSON.toJSON(resp));
            return resp;
        }
        QueryTrackReq queryTrackReq = new QueryTrackReq();
        QueryTrackParam queryTrackParam = new QueryTrackParam();
        String c = getLogisticsCompany(oOrderInfo.getLogisticsCompany());
        if (StringUtils.isBlank(c)) {
            log.error("订单:{},物流公司映射错误:{}", orderNo, oOrderInfo.getLogisticsCompany());
            throw new BusinessException("暂无物流信息,请联系客服!");
        }
        queryTrackParam.setCom(c);
        queryTrackParam.setNum(oOrderInfo.getLogisticsNo());
        queryTrackParam.setPhone(s.getMobile());
        String param = new Gson().toJson(queryTrackParam);
        queryTrackReq.setParam(param);
        queryTrackReq.setCustomer(customer);
        queryTrackReq.setSign(SignUtils.querySign(param, key, customer));

        IBaseClient baseClient = new QueryTrack();
        try {
            HttpResult httpResult = baseClient.execute(queryTrackReq);
            if (httpResult.getStatus() == HttpStatus.SC_OK && StringUtils.isNotBlank(httpResult.getBody())) {
                resp = new Gson().fromJson(httpResult.getBody(), QueryTrackResp.class);
                log.info(":>>> 订单物流状态:{},快递100返回接口:{}", orderNo, JSON.toJSON(resp));
                if (Objects.nonNull(resp)) {
                    this.setTrackCache(oOrderInfo.getOOrderNo(), oOrderInfo.getLogisticsNo(), resp);
                    return resp;
                }
                throw new BusinessException("请复制物流单号到官网查询");

            }
            return null;
        } catch (BusinessException e1) {
            throw e1;
        } catch (Exception e) {
            log.error(":>>> 获取快递100物流状态接口错误:{}", e);
            throw new BusinessException("物流状态异常");
        }
    }

    /**
     * 主动拉去获取物流信息
     *
     * @param logisticsNoList
     * @return
     */
    public void pullTrack(List<String> logisticsNoList) {
        Query query = new Query().addCriteria(Criteria.where("logisticsNo").in(logisticsNoList));
        List<OOrderInfo> subOrderList = mongoTemplate.find(query, OOrderInfo.class);
        if (CollectionUtils.isEmpty(subOrderList)) {
            log.info("pullTrack 子订单:{} 不存在", logisticsNoList);
            return;
        }
        for (OOrderInfo subOrder : subOrderList) {
            String number = subOrder.getLogisticsNo();
            String subOrderNo = subOrder.getOOrderNo();

            if (StringUtils.isBlank(subOrder.getLogisticsCompany())) {
                log.error("pullTrack 物流公司为空 物流单号:{}", number);
                continue;
            }
            String c = wayBillCompany(subOrder.getLogisticsCompany());
            if (StringUtils.isBlank(c)) {
                log.error("pullTrack 物流单号:{},物流公司映射错误:{}", number, subOrder.getLogisticsCompany());
                continue;
            }
            OrderInfo orderInfo = this.getOrderInfo(subOrder.getOrderNo());
            if (Objects.isNull(orderInfo)) {
                log.error("pullTrack 订单详情为空 物流单号:{},订单号:{}", number, subOrder.getOrderNo());
                continue;
            }

            QueryTrackReq queryTrackReq = new QueryTrackReq();
            QueryTrackParam queryTrackParam = new QueryTrackParam();

            queryTrackParam.setCom(c);
            queryTrackParam.setNum(number);
            queryTrackParam.setPhone(orderInfo.getMobile());
            String param = new Gson().toJson(queryTrackParam);
            queryTrackReq.setParam(param);
            queryTrackReq.setCustomer(customer);
            queryTrackReq.setSign(SignUtils.querySign(param, key, customer));
            IBaseClient baseClient = new QueryTrack();
            try {
                HttpResult httpResult = baseClient.execute(queryTrackReq);
                log.info("pullTrack 请求快递100 物流单号:{},结果集:{}", number, JSON.toJSON(httpResult));
                if (httpResult.getStatus() != HttpStatus.SC_OK || StringUtils.isBlank(httpResult.getBody())) {
                    log.info("pullTrack 请求返回值异常 物流单号:{},orderNo:{}", number, subOrder.getOrderNo());
                    continue;
                }
                QueryTrackResp resp = new Gson().fromJson(httpResult.getBody(), QueryTrackResp.class);
                if ("500".equals(resp.getReturnCode())) {
                    log.info("pullTrack 请求返回值异常 物流单号:{},orderNo:{},result:{}", number, subOrder.getOrderNo(), JSON.toJSON(resp));
                    continue;
                }
                //设置缓存
                this.setTrackCache(subOrder.getOOrderNo(), subOrder.getLogisticsNo(), resp);
                //更新 数据库
                SubscribeWithMapPushParamResp subscribePushParamResp = new SubscribeWithMapPushParamResp();
                SubscribeWithMapPushResult subscribeWithMapPushResult = new Gson().fromJson(httpResult.getBody(), SubscribeWithMapPushResult.class);
                subscribePushParamResp.setStatus("polling");
                subscribePushParamResp.setLastResult(subscribeWithMapPushResult);

                KuaiDi100 kuaiDi100 = mapperFacade.map(subscribePushParamResp, KuaiDi100.class);
                kuaiDi100.setNumber(number);
                kuaiDi100.setOrderNo(orderInfo.getOrderNo());
                Date now = new Date();
                query = new Query();
                query.addCriteria(Criteria.where("number").is(number));
                KuaiDi100 existKuaiDi100 = this.mongoTemplate.findOne(query, KuaiDi100.class);
                if (Objects.nonNull(existKuaiDi100)) {
                    kuaiDi100.setId(existKuaiDi100.getId());
                    kuaiDi100.setUpdatedTime(now);
                    kuaiDi100.setCreatedTime(existKuaiDi100.getCreatedTime());
                    kuaiDi100.getSubOrderNoSet().add(subOrderNo);
                    this.mongoTemplate.save(kuaiDi100);
                } else {
                    kuaiDi100.setCreatedTime(now);
                    kuaiDi100.setUpdatedTime(now);
                    kuaiDi100.getSubOrderNoSet().add(subOrderNo);
                    this.mongoTemplate.save(kuaiDi100);
                }
                log.info("pullTrack 存储数据库 物流单号:{}, kuaiDi100:{}", number, JSONObject.toJSONString(kuaiDi100));
            } catch (Exception e) {
            }
        }
    }

    private static final long THREE_DAY = 1000 * 60 * 60 * 24 * 3;

    /**
     * 主动拉去获取物流信息
     *
     * @return
     */
    public List<String> pullTrackTask() {
        List<String> orderNoList = new ArrayList<>();

        Date now = new Date();
        long nowTime = now.getTime();
        LocalDate localDate = LocalDate.now().plusDays(-15);
        ZonedDateTime zonedDateTime = localDate.atStartOfDay(ZoneId.systemDefault());
        Date date = Date.from(zonedDateTime.toInstant());

        Query query = new Query().addCriteria(
                Criteria.where("deleted").is(false)
                        .and("status").is("4")
                        .and("refundStatus").is("0")
                        .and("payTime").gte(date)
        );
        List<OrderInfo> orderInfos = mongoTemplate.find(query, OrderInfo.class);
        if (CollectionUtils.isEmpty(orderInfos)) {
            log.info("pullTrack 订单不存在");
            return orderNoList;
        }
        log.info("pullTrack 订单size :{}", orderInfos.size());
        for (OrderInfo orderInfo : orderInfos) {
            try {
                Query subOrderQuery = new Query().addCriteria(
                        Criteria.where("orderNo").is(orderInfo.getOrderNo())
                );
                OOrderInfo subOrder = mongoTemplate.findOne(subOrderQuery, OOrderInfo.class);
                if (Objects.isNull(subOrder)) {
                    log.error("pullTrackTask 子订单不存在 订单号:{}", orderInfo.getOrderNo());
                    continue;
                }
                if (StringUtils.isBlank(subOrder.getLogisticsNo())) {
                    log.error("pullTrackTask 子订单物流号不存在 订单号:{}", orderInfo.getOrderNo());
                    continue;
                }
                if (StringUtils.isBlank(subOrder.getLogisticsCompany())) {
                    log.error("pullTrackTask 子订单物流公司不存在 订单号:{}", orderInfo.getOrderNo());
                    continue;
                }
                String c = wayBillCompany(subOrder.getLogisticsCompany());
                String logisticsNo = subOrder.getLogisticsNo();

                QueryTrackReq queryTrackReq = new QueryTrackReq();
                QueryTrackParam queryTrackParam = new QueryTrackParam();

                queryTrackParam.setCom(c);
                queryTrackParam.setNum(logisticsNo);
                queryTrackParam.setPhone(orderInfo.getMobile());
                String param = new Gson().toJson(queryTrackParam);
                queryTrackReq.setParam(param);
                queryTrackReq.setCustomer(customer);
                queryTrackReq.setSign(SignUtils.querySign(param, key, customer));
                IBaseClient baseClient = new QueryTrack();

                HttpResult httpResult = baseClient.execute(queryTrackReq);
                log.info("pullTrack 请求快递100 订单号:{},结果集:{}", orderInfo.getOrderNo(), JSON.toJSON(httpResult));
                if (httpResult.getStatus() != HttpStatus.SC_OK || StringUtils.isBlank(httpResult.getBody())) {
                    log.error("pullTrack 请求返回值异常 订单号:{},orderNo:{}", orderInfo.getOrderNo(), subOrder.getOrderNo());
                    continue;
                }

                QueryTrackResp resp = new Gson().fromJson(httpResult.getBody(), QueryTrackResp.class);
                if ("500".equals(resp.getReturnCode())) {
                    log.error("pullTrack 请求返回值异常 订单号:{},orderNo:{}", orderInfo.getOrderNo(), subOrder.getOrderNo(), JSON.toJSON(resp));
                    continue;
                }
                //设置缓存
                this.setTrackCache(subOrder.getOOrderNo(), subOrder.getLogisticsNo(), resp);
                //更新 数据库
                SubscribeWithMapPushParamResp subscribePushParamResp = new SubscribeWithMapPushParamResp();
                SubscribeWithMapPushResult subscribeWithMapPushResult = new Gson().fromJson(httpResult.getBody(), SubscribeWithMapPushResult.class);
                subscribePushParamResp.setStatus("polling");
                subscribePushParamResp.setLastResult(subscribeWithMapPushResult);

                KuaiDi100 kuaiDi100 = mapperFacade.map(subscribePushParamResp, KuaiDi100.class);
                kuaiDi100.setNumber(logisticsNo);
                kuaiDi100.setOrderNo(orderInfo.getOrderNo());
                query = new Query();
                query.addCriteria(Criteria.where("number").is(logisticsNo));
                KuaiDi100 existKuaiDi100 = this.mongoTemplate.findOne(query, KuaiDi100.class);
                if (Objects.nonNull(existKuaiDi100)) {
                    if (nowTime - existKuaiDi100.getUpdatedTime().getTime() > THREE_DAY) {
                        log.info("pullTrack 快递记录已存在并且三天未更新 订单号:{},kuaiDi100:{}", orderInfo.getOrderNo(), JSONObject.toJSONString(kuaiDi100));
                        kuaiDi100.setId(existKuaiDi100.getId());
                        kuaiDi100.setUpdatedTime(now);
                        kuaiDi100.setStatus(existKuaiDi100.getStatus());
                        kuaiDi100.setCreatedTime(existKuaiDi100.getCreatedTime());
                        kuaiDi100.getSubOrderNoSet().add(subOrder.getOOrderNo());
                        this.mongoTemplate.save(kuaiDi100);
                    } else {
                        log.info("pullTrack 快递记录已存在并且三天内更新过 订单号:{}, kuaiDi100:{}", orderInfo.getOrderNo(), JSONObject.toJSONString(kuaiDi100));
                    }
                } else {
                    kuaiDi100.setCreatedTime(now);
                    kuaiDi100.setUpdatedTime(now);
                    kuaiDi100.getSubOrderNoSet().add(subOrder.getOOrderNo());
                    this.mongoTemplate.save(kuaiDi100);
                    log.info("pullTrackTask 快递记录不存在 快递记录:{}", JSONObject.toJSONString(kuaiDi100));
                }
                orderNoList.add(orderInfo.getOrderNo() + "_" + subOrder.getOOrderNo() + "_" + subOrder.getLogisticsNo());
            } catch (Exception e) {
                log.error("pullTrack order:{}, error:{}", orderInfo.getOrderNo(), e.getMessage(), e);
            }
        }
        return orderNoList;
    }


    public QueryTrackResp queryTrackByLogisticsNo(String logisticsNo, String logisticsCompany, String mobile) {
        if (StringUtils.isBlank(logisticsNo)) {
            throw new BusinessException("物流单号为空");
        }
        QueryTrackResp resp = this.getTrackCacheByExpressNo(logisticsNo);
        if (Objects.nonNull(resp)) {
            log.info("物流单号:{},物流信息在缓存中:{}", logisticsNo, JSON.toJSONString(resp));
            return resp;
        }
        QueryTrackReq queryTrackReq = new QueryTrackReq();
        QueryTrackParam queryTrackParam = new QueryTrackParam();
        String c = getLogisticsCompany(logisticsCompany);
        if (StringUtils.isBlank(c)) {
            log.error("物流单号:{},物流公司映射错误:{}", logisticsNo, logisticsCompany);
            throw new BusinessException("暂无物流信息,请联系客服!");
        }
        queryTrackParam.setCom(c);
        queryTrackParam.setNum(logisticsNo);
        queryTrackParam.setPhone(mobile);
        String param = new Gson().toJson(queryTrackParam);
        queryTrackReq.setParam(param);
        queryTrackReq.setCustomer(customer);
        queryTrackReq.setSign(SignUtils.querySign(param, key, customer));

        IBaseClient baseClient = new QueryTrack();
        try {
            HttpResult httpResult = baseClient.execute(queryTrackReq);
            if (httpResult.getStatus() == HttpStatus.SC_OK && StringUtils.isNotBlank(httpResult.getBody())) {
                resp = new Gson().fromJson(httpResult.getBody(), QueryTrackResp.class);
                log.info("物流单号:{},快递100返回接口:{}", logisticsNo, JSON.toJSON(resp));
                if (Objects.nonNull(resp) && CollectionUtils.isNotEmpty(resp.getData())) {
                    if (CollectionUtils.isNotEmpty(resp.getData())) {
                        this.setTrackCacheByExpressNo(logisticsNo, resp);
                        return resp;
                    }
                    return null;
                }
                throw new BusinessException("请复制物流单号到官网查询");
            }
            return null;
        } catch (BusinessException e1) {
            throw e1;
        } catch (Exception e) {
            log.error(":>>> 获取快递100物流状态接口错误:{}", e);
            throw new BusinessException("物流状态异常");
        }
    }

    /**
     * 实时查询地图轨迹
     *
     * @param number
     * @param orderNo
     * @param shippingTime
     * @return
     */
    public KuaiDi100 queryRealTimeTrackMap(String number, String orderNo, Date shippingTime) {
        if (Objects.isNull(shippingTime)) {
            return null;
        }
        Date date = DateTimeUtils.StringToDate(TIME, "yyyy-MM-dd HH:mm:ss");
        if (shippingTime.before(date)) {
            return null;
        }
        Query query = new Query();
        query.addCriteria(Criteria.where("orderNo").is(orderNo));
        OrderInfo order = this.mongoTemplate.findOne(query, OrderInfo.class);
        if (Objects.isNull(order)) {
            log.error(":<<<  实时查询地图轨迹，订单不存在:{}", orderNo);
            return null;
        }
        String logisticsCompany = "";
        String mobile = order.getMobile();
        String address = order.getProvince() + order.getCity() + order.getArea() + order.getAddress();
        List<OOrderInfo> subOrderList = this.mongoTemplate.find(query, OOrderInfo.class);
        if (CollectionUtils.isNotEmpty(subOrderList)) {
            OOrderInfo oOrderInfo =
                    subOrderList.stream().filter(subOrder -> "4".equals(subOrder.getStatus()) && subOrder.getLogisticsNo().equals(number)).findFirst().orElse(null);
            if (Objects.nonNull(oOrderInfo)) {
                logisticsCompany = oOrderInfo.getLogisticsCompany();
            }
        }
        query = new Query();
        query.addCriteria(Criteria.where("number").is(number));
        KuaiDi100 kuaiDi100;
        KuaiDi100RealTime kuaiDi100RealTime = this.mongoTemplate.findOne(query, KuaiDi100RealTime.class);
        String comCode = this.getLogisticsCompany(logisticsCompany);
        if (Objects.nonNull(kuaiDi100RealTime)) {
            kuaiDi100 = new KuaiDi100();
            BeanUtils.copyProperties(kuaiDi100RealTime, kuaiDi100);
            kuaiDi100.setReceiveAddress(address);
            kuaiDi100.setReceiveMobile(mobile.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2"));
            kuaiDi100.setReceiveName(order.getName());
            kuaiDi100.setLogisticsCompany(logisticsCompany);
            return kuaiDi100;
        }
        kuaiDi100 = new KuaiDi100();
        kuaiDi100.setReceiveName(order.getName());
        kuaiDi100.setLogisticsCompany(logisticsCompany);
        kuaiDi100.setReceiveAddress(address);
        kuaiDi100.setReceiveMobile(mobile.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2"));
        kuaiDi100.setNumber(number);
        kuaiDi100.setStatus("polling");
        kuaiDi100.setBillstatus("got");
        SubscribeWithMapPushResult lastResult = new SubscribeWithMapPushResult();
        lastResult.setState("1");
        lastResult.setCom("ems");
        lastResult.setNu(number);
        lastResult.setStatus("200");
        lastResult.setCondition("00");
        OrderNoLogistics orderNoLogistics = new OrderNoLogistics(orderNo, number, shippingTime);
        String statusLogistics = orderNoLogistics.getStatus();
        List<SubscribePushData> dataList = new ArrayList<>();
        SubscribePushData subscribePushData = null;
        switch (statusLogistics) {
            case "核验中":
                subscribePushData = new SubscribePushData();
                subscribePushData.setStatus(orderNoLogistics.getStatus());
                subscribePushData.setContext(orderNoLogistics.getTips());
                subscribePushData.setTime(orderNoLogistics.getTime());
                subscribePushData.setStatusCode("-100");
                dataList.add(subscribePushData);
                break;
            case "打包中":
                subscribePushData = new SubscribePushData();
                subscribePushData.setStatus(orderNoLogistics.getStatus());
                subscribePushData.setContext(orderNoLogistics.getTips());
                subscribePushData.setTime(orderNoLogistics.getTime());
                subscribePushData.setStatusCode("-200");
                dataList.add(subscribePushData);
                subscribePushData = new SubscribePushData();
                subscribePushData.setStatus("核验中");
                subscribePushData.setContext(tips1);
                subscribePushData.setTime(orderNoLogistics.getCheckTime());
                subscribePushData.setStatusCode("-100");
                dataList.add(subscribePushData);
                break;
            case "等待揽收":
                subscribePushData = new SubscribePushData();
                subscribePushData.setStatus(orderNoLogistics.getStatus());
                subscribePushData.setContext(orderNoLogistics.getTips());
                subscribePushData.setTime(orderNoLogistics.getTime());
                subscribePushData.setStatusCode("-300");
                dataList.add(subscribePushData);
                subscribePushData = new SubscribePushData();
                subscribePushData.setStatus("打包中");
                subscribePushData.setContext(tips2);
                subscribePushData.setTime(orderNoLogistics.packTime);
                subscribePushData.setStatusCode("-200");
                dataList.add(subscribePushData);
                subscribePushData = new SubscribePushData();
                subscribePushData.setStatus("核验中");
                subscribePushData.setContext(tips1);
                subscribePushData.setTime(orderNoLogistics.getCheckTime());
                subscribePushData.setStatusCode("-100");
                dataList.add(subscribePushData);
                break;
        }

        lastResult.setData(dataList);
        kuaiDi100.setLastResult(lastResult);
        return kuaiDi100;
    }

    private OrderInfo getOrderInfo(String orderNo) {
        Query query = new Query().addCriteria(Criteria.where("orderNo").is(orderNo));
        OrderInfo orderInfo = mongoTemplate.findOne(query, OrderInfo.class);
        return orderInfo;
    }

    private OOrderInfo getSubOrderInfo(String subOrderNo) {
        Query query = new Query().addCriteria(Criteria.where("oOrderNo").is(subOrderNo));
        OOrderInfo orderInfo = mongoTemplate.findOne(query, OOrderInfo.class);
        return orderInfo;
    }

    private String getLogisticsCompany(String l) {
        log.info(":>>> 获取物流公司:{}", l);
        if ("顺丰".equals(l) || "顺丰快递".equals(l) || "顺丰物流".equals(l)) {
            l = "顺丰速运";
        } else if ("圆通".equals(l) || "圆通快递".equals(l) || "圆通物流".equals(l) || "圆通速递".equals(l)) {
            l = "圆通快运";
        } else if ("申通快递".equals(l) || "申通".equals(l)) {
            l = "申通快递";
        } else if ("百世快递".equals(l) || "百世".equals(l)) {
            l = "百世快递";
        } else if ("中通".equals(l) || "中通快递".equals(l)) {
            l = "中通快递";
        } else if ("邮政航空EMS".equals(l) || "中国邮政".equals(l) || "中国邮政".equals(l) || "邮政快递".equals(l) || "邮政".equals(l) || "EMS".equals(l) || "全球邮政航空EMS".equals(l)) {
            l = "邮政快递包裹";
        } else if ("百世快递".equals(l) || "百世".equals(l)) {
            l = "百世快递";
        }
        ExpressCompany e = expressCompanyService.findByName(l);
        if (Objects.isNull(e)) {
            return "";
        }
        return e.getCode();
    }

    private QueryTrackResp getTrackCache(String subOrderNo, String expressNo) {
        String key = getTrackCacheKey(subOrderNo, expressNo);
        Object v = redisTemplate.opsForValue().get(key);
        log.info(":>> 缓存:{} 的物流信息:{}", key, v);
        if (Objects.isNull(v)) {
            return null;
        }
        QueryTrackResp vO = JSON.parseObject((String) v, QueryTrackResp.class);
        return vO;
    }

    private QueryTrackResp getTrackCacheByExpressNo(String expressNo) {
        String key = getNewTrackCacheKey(expressNo);
        Object v = redisTemplate.opsForValue().get(key);
        log.info(":>> 缓存:{} 的物流信息:{}", key, v);
        if (Objects.isNull(v)) {
            return null;
        }
        QueryTrackResp vO = JSON.parseObject((String) v, QueryTrackResp.class);
        return vO;
    }

    private void setTrackCacheByExpressNo(String expressNo, QueryTrackResp data) {
        String key = getNewTrackCacheKey(expressNo);
        redisTemplate.opsForValue().set(key, JSON.toJSONString(data), 24 * 3600, TimeUnit.SECONDS);
    }

    private void setTrackCache(String subOrderNo, String expressNo, QueryTrackResp data) {
        String key = getTrackCacheKey(subOrderNo, expressNo);
        redisTemplate.opsForValue().set(key, JSON.toJSONString(data), 36 * 3600, TimeUnit.SECONDS);
    }

    private String getTrackCacheKey(String subOrderNo, String expressNo) {
        if (StringUtils.isBlank(subOrderNo) || StringUtils.isBlank(expressNo)) {
            log.error(":>>> 子订单编号或物流单号为空");
            throw new BusinessException("子订单编号或物流单号为空");
        }
        String key = String.format(KUAI_100_EXPRESS_RPEFIX, subOrderNo, expressNo + "");
        log.info(":>>> 子订单:{},物流:{} 缓存key:{}", subOrderNo, expressNo, key);
        return key;
    }

    private String getNewTrackCacheKey(String expressNo) {
        String key = String.format(KUAI_100_NEW_EXPRESS_RPEFIX, expressNo);
        return key;
    }

    private void getMapFromKuaiDi100(String com, String number,
                                     String mobile,
                                     String from, String to) {
        QueryTrackReq queryTrackReq = new QueryTrackReq();
        QueryTrackParam queryTrackParam = new QueryTrackParam();
        queryTrackParam.setCom(com);
        queryTrackParam.setNum(number);
        queryTrackParam.setPhone(mobile);
        queryTrackParam.setFrom(from);
        queryTrackParam.setTo(to);
        queryTrackParam.setResultv2("2");
        String param = new Gson().toJson(queryTrackParam);
        queryTrackReq.setParam(param);
        queryTrackReq.setCustomer(customer);
        queryTrackReq.setSign(SignUtils.querySign(param, key, customer));
        IBaseClient baseClient = new QueryTrackMap();
        HttpResult result = null;
        try {
            result = baseClient.execute(queryTrackReq);
            QueryTrackMapResp queryTrackMapResp = new Gson().fromJson(result.getBody(), QueryTrackMapResp.class);


        } catch (Exception e) {
            log.error(":>>> 实时获取快递100接口错误:{}", e);
            return;
        }
    }
}
